package com.net.xpay.core.manager.impl;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.common.annotation.ReadTransactional;
import com.net.common.annotation.WriteTransactional;
import com.net.common.dao.BasicMapper;
import com.net.common.dao.Page;
import com.net.common.manager.AbstractVersionedManager;
import com.net.noah.core.service.SerialNumberService;
import com.net.xpay.core.dao.PayTransMapper;
import com.net.xpay.core.domain.PayTrans;
import com.net.xpay.core.enums.PayTransStatus;
import com.net.xpay.core.manager.PayTransManager;
import com.net.xpay.core.model.PayTransSearchModel;
import com.net.xpay.core.model.QueryRepeatModel;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@Component
@ReadTransactional
public class PayTransManagerImpl extends AbstractVersionedManager<PayTrans> implements PayTransManager{

    @Autowired
    private PayTransMapper mapper;

    @Autowired
    private SerialNumberService serialNumberService;

    @Override
    @WriteTransactional(propagation = Propagation.SUPPORTS)
    public int save(PayTrans obj) {
        Preconditions.checkArgument(obj.getId() == null);
        obj.setId(serialNumberService.getLongSerialNumber(getTableFullName()));
        //外部交易号
        obj.setOutBizNo(obj.getUserId() + "-" + obj.getId());
        return super.save(obj);
    }

    @Override
    protected BasicMapper<Long, PayTrans> getMapper() {
        return mapper;
    }

    @Override
    public List<PayTrans> listByPayTransBatchId(Long userId, Long payTransBatchId) {
        Preconditions.checkArgument(userId != null && payTransBatchId != null);
        PayTrans condition = new PayTrans();
        condition.setUserId(userId);
        condition.setPayTransBatchId(payTransBatchId);
        return listByCondition(condition, new ArrayList<>());
    }

    @Override
    public int batchSave(List<PayTrans> payTrans) {
        if (CollectionUtils.isEmpty(payTrans)) {
            return 0;
        }
        for (PayTrans trans : payTrans) {
            LocalDateTime now = LocalDateTime.now();
            trans.setId(serialNumberService.getLongSerialNumber(getTableFullName()));
            //外部交易号
            trans.setOutBizNo(trans.getUserId() + "-" + trans.getId());
            trans.setCreateTime(now);
            trans.setModifyTime(now);
            trans.setVersion(0L);
        }
        return mapper.batchSave(payTrans);
    }

    @Override
    public int updateStatusByPayTransBatchId(Long userId, Long payTransBatchId, PayTransStatus status, Boolean free, LocalDateTime endTime) {
        Preconditions.checkArgument(userId != null && payTransBatchId != null && status != null);
        return mapper.updateStatusByPayTransBatchId(userId, payTransBatchId, status, free, endTime);
    }

    @Override
    public List<PayTrans> findByUserIdAndOutBizNoIn(Long userId, List<String> outBizNos) {
        Preconditions.checkArgument(userId != null && CollectionUtils.isNotEmpty(outBizNos));
        return nonEmptyList(mapper.findByUserIdAndOutBizNoIn(userId, outBizNos));
    }

    @Override
    public List<PayTrans> search(PayTransSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        Page page = new Page(searchModel);
        page.addOrder("id", "desc");
        return nonEmptyList(mapper.search(searchModel, page));
    }

    @Override
    public List<PayTrans> list(PayTransSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        return nonEmptyList(mapper.list(searchModel));
    }

    @Override
    public long searchCount(PayTransSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        return mapper.searchCount(searchModel);
    }

    @Override
    public int batchUpdate(List<PayTrans> payTrans) {
        if (CollectionUtils.isEmpty(payTrans)) {
            return 0;
        }
        for (PayTrans record : payTrans) {
            LocalDateTime now = LocalDateTime.now();
            record.setModifyTime(now);
            record.setVersion(record.getVersion() + 1L);
        }

        return mapper.batchUpdate(payTrans);
    }

    @Override
    public PayTrans findByImportBizNo(Long userId, String importBatchNo, String importBizNo) {
        Preconditions.checkArgument(userId != null && !Strings.isNullOrEmpty(importBatchNo) && !Strings.isNullOrEmpty(importBizNo));
        PayTrans condition = new PayTrans();
        condition.setUserId(userId);
        condition.setImportBatchNo(importBatchNo);
        condition.setImportBizNo(importBizNo);

        return getByCondition(condition);
    }

    @Override
    public long statSingleVeryCount(LocalDateTime startTime, LocalDateTime endTime) {
        return mapper.statSingleVeryCount(startTime, endTime);
    }

    @Override
    public List<Long> listSingleVeryMerchantIds(LocalDateTime startTime, LocalDateTime endTime) {
        Preconditions.checkArgument(startTime != null && endTime != null);
        List<Long> rets = mapper.listSingleVeryMerchantIds(startTime, endTime);
        return rets == null ? new ArrayList<>() : rets;
    }

    @Override
    public List<QueryRepeatModel> queryMayRepeatPayTransWithType1(Long userId, LocalDateTime minCreateTime, LocalDateTime maxCreateTime) {
        Preconditions.checkArgument(userId != null && minCreateTime != null && maxCreateTime != null);
        List<QueryRepeatModel> models = mapper.queryMayRepeatPayTransWithType1(userId, minCreateTime, maxCreateTime);
        return models == null ? new ArrayList<>() : models;
    }

    @Override
    public List<QueryRepeatModel> queryMayRepeatPayTransWithType2(Long userId, LocalDateTime minCreateTime, LocalDateTime maxCreateTime) {
        Preconditions.checkArgument(userId != null && minCreateTime != null && maxCreateTime != null);
        List<QueryRepeatModel> models = mapper.queryMayRepeatPayTransWithType2(userId, minCreateTime, maxCreateTime);
        return models == null ? new ArrayList<>() : models;
    }

    @Override
    public PayTrans findById(Long userId, Long id) {
        Preconditions.checkArgument(userId != null && id != null);
        PayTrans condition = new PayTrans();
        condition.setUserId(userId);
        condition.setId(id);

        return getByCondition(condition);
    }

    @Override
    public long statFailSingleVeryCount(LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        return mapper.statFailSingleVeryCount(minEndTime, maxEndTime);
    }

    @Override
    public long statUserSingleVeryCount(Long userId, LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(userId != null && minEndTime != null && maxEndTime != null);
        return mapper.statUserSingleVeryCount(userId,minEndTime, maxEndTime);
    }

    @Override
    public long statUserFailSingleVeryCount(Long userId, LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(userId != null && minEndTime != null && maxEndTime != null);
        return mapper.statUserFailSingleVeryCount(userId,minEndTime, maxEndTime);
    }

    @Override
    public long statPayTransPayeeAlipayAccount(LocalDateTime minEndTime, LocalDateTime maxEndTime) {

        return mapper.statPayTransPayeeAlipayAccount(minEndTime, maxEndTime);
    }

    @Override
    public long statUserLargeCount(Long userId, LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(userId != null && minEndTime != null && maxEndTime != null);
        return mapper.statUserLargeCount(userId,minEndTime, maxEndTime);
    }
}
